package com.octopus.json;

import java.util.ArrayDeque;

import org.apache.log4j.Logger;

import com.octopus.string.StringUtils;

public class JsonUtils {
	
	private static final Logger logger = Logger.getLogger(JsonUtils.class.getName());
	
	public static Json createJsonObject(){
		Json json = new Json();
		json.initObject();
		return json;
	}
	public static Json createJsonArray(){
		Json json = new Json();
		json.initArray();
		return json;
	}
	public static Json createSimpleValueJson(Integer value){
		Json json = new Json();
		json.initSimpleValue(value);
		return json;
	}
	public static Json createSimpleValueJson(Long value){
		Json json = new Json();
		json.initSimpleValue(value);
		return json;
	}
	public static Json createSimpleValueJson(Double value){
		Json json = new Json();
		json.initSimpleValue(value);
		return json;
	}
	public static Json createSimpleValueJson(String value){
		Json json = new Json();
		json.initSimpleValue(value);
		return json;
	}
	
	/**
	 * @Note Delimiter : {[]},'":.
	 * <br/>. means nothing
	 */
	public static void readJson(String jsonString, ArrayDeque<Character> ad_delimiter, ArrayDeque<String> ad_data) throws NotValidJsonString{
		if(jsonString == null){
			return;
		}
		jsonString = jsonString.trim();
		if(jsonString.length() == 0){
			return;
		}
		if(ad_delimiter == null){
			return;
		}
		if(ad_data == null){
			return;
		}
		ad_delimiter.clear();
		ad_data.clear();
		
		ArrayDeque<Character> ad_delimiter_match = new ArrayDeque<Character>();
		StringBuffer tempdata = new StringBuffer();
		char[] chars = jsonString.toCharArray();
		Character escape = null;
		int index = 0;
		StringBuffer sb = new StringBuffer();
		for(char c : chars){
			sb.append(c);
			index++;
			if(escape != null){
				if(c == 'r'){
					c = '\r';
				}else if(c == 'n'){
					c = '\n';
				}else if(c == 't'){
					c = '\t';
				}
				tempdata.append(c);
				escape = null;
				continue;
			}
			if(c == '\\'){
				escape = '\\';
				continue;
			}
			if(c != '"' && !ad_delimiter.isEmpty() && ad_delimiter.getLast() == '"'){
				if(!isLastPairQuotationDelimiter(ad_delimiter)){
					tempdata.append(c);
					continue;
				}
			}else if(c != '\'' && !ad_delimiter.isEmpty() && ad_delimiter.getLast() == '\''){
				if(!isLastPairQuotationDelimiter(ad_delimiter)){
					tempdata.append(c);
					continue;
				}
			}
			
			if(c == '{'){
				ad_delimiter_match.add(c);
				ad_delimiter.add(c);
				tempdata.delete(0, tempdata.length());
				continue;
			}else if(c == '}'){
				if(ad_delimiter.isEmpty()){
					throw new NotValidJsonString(StringUtils.concat("} is the fist delimiter is not allowed at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
				
				Character matchedChar = ad_delimiter_match.peekLast();
				if(matchedChar == null || matchedChar != '{'){
					throw new NotValidJsonString(StringUtils.concat("Can't find the matched left brace at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
				ad_delimiter_match.removeLast();
				
				if(ad_delimiter.getLast() == '"' || ad_delimiter.getLast() == '\''){
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}else if(ad_delimiter.getLast() == ':'){
					if(tempdata.length() == 0){
						throw new NotValidJsonString(StringUtils.concat("No data before delimiter } at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}else{
						ad_data.add(tempdata.toString().trim());
						tempdata.delete(0, tempdata.length());
						ad_delimiter.add(c);
						continue;
					}
				}else if(ad_delimiter.getLast() == '}' || ad_delimiter.getLast() == ']'){
					String value = tempdata.toString().trim();
					if(value.length() != 0){
						throw new NotValidJsonString(StringUtils.concat("There is data between ]}/}} at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
					tempdata.delete(0, tempdata.length());
					ad_delimiter.add(c);
					continue;
				}else if(ad_delimiter.getLast() == '{'){
					String value = tempdata.toString().trim();
					if(value.length() != 0){
						throw new NotValidJsonString(StringUtils.concat("There is data between {} at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
					tempdata.delete(0, tempdata.length());
					ad_delimiter.add('.');
					ad_delimiter.add(c);
					continue;
				}else{
					throw new NotValidJsonString(StringUtils.concat("Unvalid delimiter['",String.valueOf(ad_delimiter.getLast()),"'] before } at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
			}else if(c == '['){
				String value = tempdata.toString().trim();
				if(value.length() != 0){
					throw new NotValidJsonString(StringUtils.concat("There is data before [ at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
				ad_delimiter_match.add(c);
				
				tempdata.delete(0, tempdata.length());
				
				if(ad_delimiter.isEmpty()){
					ad_delimiter.add(c);
					continue;
				}
				if(ad_delimiter.getLast() == '[' || ad_delimiter.getLast() == '{' || ad_delimiter.getLast() == ':' || ad_delimiter.getLast() == ','){
					ad_delimiter.add(c);
				}else{
					throw new NotValidJsonString(StringUtils.concat("The delimiter of [ can't appear after the delimiters of ], }, \", \' at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
				
				continue;
			}else if(c == ']'){
				if(ad_delimiter.isEmpty()){
					throw new NotValidJsonString(StringUtils.concat("] is not allowed to be the first delimiter at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
				
				Character matchedChar = ad_delimiter_match.peekLast();
				if(matchedChar == null || matchedChar != '['){
					throw new NotValidJsonString(StringUtils.concat("Can't find matched left square bracket at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
				ad_delimiter_match.removeLast();
				
				if(ad_delimiter.getLast() == '"' || ad_delimiter.getLast() == '\'' || ad_delimiter.getLast() == '}' || ad_delimiter.getLast() == ']'){
					String value = tempdata.toString().trim();
					if(value.length() != 0){
						throw new NotValidJsonString(StringUtils.concat("There is data between ] and }/\" at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}else if(ad_delimiter.getLast() == ','){
					if(tempdata.length() != 0){
						ad_data.add(tempdata.toString().trim());
						tempdata.delete(0, tempdata.length());
						ad_delimiter.add(c);
						continue;
					}else{
						throw new NotValidJsonString(StringUtils.concat("Null data just before delimiter ] at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
				}else if(ad_delimiter.getLast() == '['){
					String temp = tempdata.toString().trim();
					if(temp.length() == 0){
						ad_delimiter.add('.');
					}else{
						ad_data.add(temp);
					}
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}else{
					throw new NotValidJsonString(StringUtils.concat(":/{ before the delimiter of ] at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
			}else if(c == '"'){
				//Under such condition, the delimiter of ' can't be the last delimiter.
				if(ad_delimiter.isEmpty()){
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}
				if(ad_delimiter.getLast() == '"'){
					Character lastDelimiter = ad_delimiter.removeLast();
					if(ad_delimiter.isEmpty()){
						// do nothing
					}else if(ad_delimiter.getLast() == '"' || ad_delimiter.getLast() == '\''){
						throw new NotValidJsonString(StringUtils.concat("More than two same continuous delimiters of \" at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
					ad_delimiter.add(lastDelimiter);
					ad_delimiter.add(c);
					ad_data.add(tempdata.toString());
					tempdata.delete(0, tempdata.length());
					continue;
				}else if(ad_delimiter.getLast() == '{' || ad_delimiter.getLast() == '[' || ad_delimiter.getLast() == ',' || ad_delimiter.getLast() == ':'){
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}else{
					throw new NotValidJsonString(StringUtils.concat("Unvalid delimiter before \" is ", String.valueOf(ad_delimiter.getLast()) ," at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
			}else if(c == '\''){
				//Under such condition, the delimiter of " can't be the last delimiter.
				if(ad_delimiter.isEmpty()){
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}
				if(ad_delimiter.getLast() == '\''){
					Character lastDelimiter = ad_delimiter.removeLast();
					if(ad_delimiter.isEmpty()){
						//do nothing.
					}else{
						if(ad_delimiter.getLast() == '"' || ad_delimiter.getLast() == '\''){
							throw new NotValidJsonString(StringUtils.concat("More than two same continuous delimiters of \" at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
						}
					}
					ad_delimiter.add(lastDelimiter);
					ad_delimiter.add(c);
					ad_data.add(tempdata.toString());
					tempdata.delete(0, tempdata.length());
					continue;
				}else if(ad_delimiter.getLast() == '{' || ad_delimiter.getLast() == '[' || ad_delimiter.getLast() == ',' || ad_delimiter.getLast() == ':'){
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}else{
					throw new NotValidJsonString(StringUtils.concat("Unvalid delimiter before ['] is [", String.valueOf(ad_delimiter.getLast()) ,"] at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
			}else if(c == ':'){
				if(ad_delimiter.isEmpty()){
					throw new NotValidJsonString(StringUtils.concat(": is allowed to be the first delimiter at ", String.valueOf(index)));
				}
				
				if(ad_delimiter.getLast() != '{' && ad_delimiter.getLast() != ',' && !isLastPairQuotationDelimiter(ad_delimiter)){
					throw new NotValidJsonString(StringUtils.concat("Not valid delimiter ", String.valueOf(ad_delimiter.getLast()), " before : at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
				
				String dd = tempdata.toString().trim();
				if(isLastPairQuotationDelimiter(ad_delimiter)){
					if(dd.length() != 0){
						throw new NotValidJsonString(StringUtils.concat(dd, " exists before : at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
					ad_delimiter.add(c);
					continue;
				}
				ad_delimiter.add(c);
				ad_data.add(dd);
				tempdata.delete(0, tempdata.length());
				
				continue;
			}else if(c == ','){
				if(ad_delimiter.isEmpty()){
					throw new NotValidJsonString(StringUtils.concat(", is not allowed to be the first delimiter. at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
				if(ad_delimiter.getLast() == '{' || ad_delimiter.getLast() == '['){
					String value = tempdata.toString().trim();
					if(value.length() == 0){
						throw new NotValidJsonString(StringUtils.concat("between {/[ and , there must be non-null data at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
					ad_delimiter.add(c);
					ad_data.add(value);
					tempdata.delete(0, tempdata.length());
					continue;
				}else if(ad_delimiter.getLast() == ':' || ad_delimiter.getLast() == ','){
					ad_delimiter.add(c);
					ad_data.add(tempdata.toString().trim());
					tempdata.delete(0, tempdata.length());
					continue;
				}else if(ad_delimiter.getLast() == ']' || ad_delimiter.getLast() == '}'){
					String value = tempdata.toString().trim();
					if(value.length() != 0){
						throw new NotValidJsonString(StringUtils.concat("between }/] and , there must be none data at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}else if(ad_delimiter.getLast() == '"'){
					String value = tempdata.toString().trim();
					if(value.length() != 0){
						throw new NotValidJsonString(StringUtils.concat("before comma there is non-null data after quotation mark delimiter at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}else if(ad_delimiter.getLast() == '\''){
					String value = tempdata.toString().trim();
					if(value.length() != 0){
						throw new NotValidJsonString(StringUtils.concat("before comma there is non-null data after single quotation mark delimiter at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
					}
					ad_delimiter.add(c);
					tempdata.delete(0, tempdata.length());
					continue;
				}
			}
			Character latestChar = ad_delimiter.peekLast(); 
			if(latestChar != null && (
					latestChar == '}'
					||
					latestChar == ']'
					||
					isLastPairQuotationDelimiter(ad_delimiter)
					) ){
				if(String.valueOf(c).trim().length() != 0){
					throw new NotValidJsonString(StringUtils.concat("there should be no such data[",String.valueOf(c),"] after ] } and a pair of qoutation marks at ", String.valueOf(index), " processed string:[",sb.toString(),"]"));
				}
			}
			tempdata.append(c);
		}
		
		if(ad_delimiter_match.size() != 0){
			throw new NotValidJsonString(StringUtils.concat("There are still some non-matched delimiters ", ad_delimiter_match.toString(), " processed string:[",sb.toString(),"]"));
		}
		String finalValue = tempdata.toString().trim();
		if(finalValue.length() != 0){
			ad_data.add(finalValue);
		}
	}
	
	public static boolean isLastPairQuotationDelimiter(ArrayDeque<Character> delimiter){
		if(delimiter == null || delimiter.isEmpty()){
			return false;
		}
		if(delimiter.getLast() == '\''){
			Character lastChar = delimiter.removeLast();
			if(delimiter.isEmpty()){
				delimiter.add(lastChar);
				return false;
			}else if(delimiter.getLast() == '\''){
				delimiter.add(lastChar);
				return true;
			}else{
				delimiter.add(lastChar);
				return false;
			}
		}else if(delimiter.getLast() == '"'){
			Character lastChar = delimiter.removeLast();
			if(delimiter.isEmpty()){
				delimiter.add(lastChar);
				return false;
			}else if(delimiter.getLast() == '"'){
				delimiter.add(lastChar);
				return true;
			}else{
				delimiter.add(lastChar);
				return false;
			}
		}else{
			return false;
		}
	}
	
	public static Json readSimpleJson(String simpleJsonString, boolean forceString){
		if(simpleJsonString == null){
			return null;
		}
		Json json = null;
		if(forceString){
			return JsonUtils.createSimpleValueJson(simpleJsonString);
		}
		simpleJsonString = simpleJsonString.trim();
		if(simpleJsonString.matches("(\\+|\\-)?[0-9]+")){
			try{
				Integer firstTry = Integer.parseInt(simpleJsonString);
				json = JsonUtils.createSimpleValueJson(firstTry);
				return json;
			}catch(Exception e){
				logger.debug(e);
			}
			try{
				Long secondTry = Long.parseLong(simpleJsonString);
				json = JsonUtils.createSimpleValueJson(secondTry);
				return json;
			}catch(Exception e){
				logger.debug(e);
			}
			logger.fatal(StringUtils.concat(simpleJsonString, " can't be converted into Integer or Long"));
			return null;
		}else if(simpleJsonString.matches("(\\+|\\-)?[0-9]*\\.[0-9]*")){
			try{
				Double firstTry = Double.parseDouble(simpleJsonString);
				json = JsonUtils.createSimpleValueJson(firstTry);
				return json;
			}catch(Exception e){
				logger.debug(e);
			}
			logger.fatal(StringUtils.concat(simpleJsonString, " can't be converted into Double"));
			return null;
		}else{
			return JsonUtils.createSimpleValueJson(simpleJsonString);
		}
	}
	
	private static String[] readJsonUnit(ArrayDeque<Character> ad_delimiter, ArrayDeque<String> ad_data) throws NotValidJsonDataQueue, NotValidJsonDelimiterQueue{
		/**
		 * result[0] is the string value.
		 * result[1] is the string indicator. Y/N, Y means that's the forced string value, N means that's is not the forced string value
		 */
		if(ad_delimiter == null || ad_delimiter.size() == 0){
			throw new NotValidJsonDelimiterQueue("empty delimiter queue");
		}
		if(ad_data == null || ad_data.size() == 0){
			throw new NotValidJsonDataQueue("empty data queue");
		}
		String[] result = new String[2];
		Character delimiter = ad_delimiter.peekFirst();
		if(delimiter == null){
			throw new NotValidJsonDelimiterQueue("after { delimiter is null");
		}
		if(delimiter == '"' || delimiter == '\''){
			ad_delimiter.removeFirst();
			delimiter = ad_delimiter.peekFirst();
			if(delimiter == null){
				throw new NotValidJsonDelimiterQueue("delimiter is null, string quotation is not enclosed");
			}
			if(delimiter != '"' && delimiter != '\''){
				throw new NotValidJsonDelimiterQueue("string quotation is not enclosed");
			}
			ad_delimiter.removeFirst();
			String value = ad_data.peekFirst();
			if(value == null){
				throw new NotValidJsonDataQueue("data is null");
			}
			ad_data.removeFirst();
			result[0] = value;
			result[1] = "Y";
		}else{
			String value = ad_data.peekFirst();
			if(value == null){
				throw new NotValidJsonDataQueue("data is null");
			}
			ad_data.removeFirst();
			result[0] = value;
			result[1] = "N";
		}
		return result;
	}
	
	
	public static Json readJsonArray(ArrayDeque<Character> ad_delimiter, ArrayDeque<String> ad_data) throws NotValidJsonDataQueue, NotValidJsonDelimiterQueue{
		if(ad_delimiter == null || ad_delimiter.size() == 0){
			throw new NotValidJsonDelimiterQueue("empty delimiter queue");
		}
		/*
		if(ad_data == null || ad_data.size() == 0){
			throw new NotValidJsonDataQueue("empty data queue");
		}
		*/
		Character delimiter = ad_delimiter.peekFirst();
		if(delimiter == null){
			throw new NotValidJsonDelimiterQueue("after [ delimiter is null");
		}
		Json result = JsonUtils.createJsonArray();
		while(true){
			if(delimiter == null){
				throw new NotValidJsonDelimiterQueue(" before ] is null delimiter ");
			}
			Json jsonValue = null;
			if(delimiter == '\'' || delimiter == '"'){
				String[] stringResult = readJsonUnit(ad_delimiter, ad_data);
				if("Y".equals(stringResult[1])){
					jsonValue = readSimpleJson(stringResult[0], true);
				}else{
					jsonValue = readSimpleJson(stringResult[0], false);
				}
				result.appendArrayWithJson(jsonValue);
			}else if(delimiter == '{'){
				ad_delimiter.removeFirst();
				jsonValue = readJsonObject(ad_delimiter, ad_data);
				result.appendArrayWithJson(jsonValue);
			}else if(delimiter == '['){
				ad_delimiter.removeFirst();
				jsonValue = readJsonArray(ad_delimiter, ad_data);
				result.appendArrayWithJson(jsonValue);
			}else if(delimiter == ','){
				String[] stringResult = readJsonUnit(ad_delimiter, ad_data);
				if("Y".equals(stringResult[1])){
					jsonValue = readSimpleJson(stringResult[0], true);
				}else{
					jsonValue = readSimpleJson(stringResult[0], false);
				}
				result.appendArrayWithJson(jsonValue);
			}else if(delimiter == '.'){
				ad_delimiter.removeFirst();
				delimiter = ad_delimiter.peekFirst();
				if(delimiter == null){
					throw new NotValidJsonDelimiterQueue(StringUtils.concat(" after . is null "));
				}
				if(delimiter != ']'){
					throw new NotValidJsonDelimiterQueue(StringUtils.concat(" after . is not ] "));
				}
				ad_delimiter.removeFirst();
				return result;
			}else if(delimiter == ']'){
				String[] stringResult = readJsonUnit(ad_delimiter, ad_data);
				if("Y".equals(stringResult[1])){
					jsonValue = readSimpleJson(stringResult[0], true);
				}else{
					jsonValue = readSimpleJson(stringResult[0], false);
				}
				ad_delimiter.removeFirst();
				result.appendArrayWithJson(jsonValue);
				return result;
			}else{
				throw new NotValidJsonDelimiterQueue(StringUtils.concat(" not allowed delimiter of array [",String.valueOf(delimiter),"]"));
			}
			
			delimiter = ad_delimiter.peekFirst();
			if(delimiter == null){
				throw new NotValidJsonDelimiterQueue(" delimiter is null, null is not allowed ");
			}
			if(delimiter == ','){
				ad_delimiter.removeFirst();
				delimiter = ad_delimiter.peekFirst();
				continue;
			}else if(delimiter == ']'){
				ad_delimiter.removeFirst();
				return result;
			}else{
				throw new NotValidJsonDelimiterQueue(StringUtils.concat(" except , and ] other delimiters are not allowed [",String.valueOf(delimiter),"] "));
			}
		}
	}
	

	/**
	 * @param ad_delimiter
	 * @param ad_data
	 * @return
	 * @throws NotValidJsonDataQueue
	 * @throws NotValidJsonDelimiterQueue
	 */
	public static Json readJsonObject(ArrayDeque<Character> ad_delimiter, ArrayDeque<String> ad_data) throws NotValidJsonDataQueue, NotValidJsonDelimiterQueue{
		if(ad_delimiter == null || ad_data == null){
			return null;
		}
		Json result = JsonUtils.createJsonObject();
		boolean first = true;
		while(true){
			String key = null;
			Json value = null;
			if(first){
				first = false;
				Character period_delimiter = ad_delimiter.peekFirst();
				if(period_delimiter == null){
					throw new NotValidJsonDelimiterQueue(StringUtils.concat(" null delimiter follow { "));
				}
				
				if(period_delimiter == '.'){
					ad_delimiter.removeFirst();
					period_delimiter = ad_delimiter.peekFirst();
					if(period_delimiter == null){
						throw new NotValidJsonDelimiterQueue(" after . is null ");
					}
					if(period_delimiter != '}'){
						throw new NotValidJsonDelimiterQueue(" after . is not } ");
					}
					ad_delimiter.removeFirst();
					return JsonUtils.createJsonObject();
				}
			}
			String readResult[] = readJsonUnit(ad_delimiter, ad_data);
			if("Y".equals(readResult[1])){
				key = readResult[0];
			}else{
				key = readResult[0].trim();
			}
			Character delimiter = ad_delimiter.peekFirst();
			if(delimiter == null || delimiter != ':'){
				throw new NotValidJsonDelimiterQueue(" after key is not [:] ");
			}
			ad_delimiter.removeFirst();
			delimiter = ad_delimiter.peekFirst();
			if(delimiter == null){
				throw new NotValidJsonDelimiterQueue(" [:] is the last delimiter ");
			}
			if(delimiter == '\'' || delimiter == '"'){
				readResult = readJsonUnit(ad_delimiter, ad_data);
				if("Y".equals(readResult[1])){
					value = readSimpleJson(readResult[0], true);
				}else{
					value = readSimpleJson(readResult[0], false);
				}
				result.appendKeyJsonValue(key, value);
			}else if(delimiter == '{'){
				ad_delimiter.removeFirst();
				value = readJsonObject(ad_delimiter, ad_data);
				result.appendKeyJsonValue(key, value);
			}else if(delimiter == '['){
				ad_delimiter.removeFirst();
				value = readJsonArray(ad_delimiter, ad_data);
				result.appendKeyJsonValue(key, value);
			}else if(delimiter == ','){
				readResult = readJsonUnit(ad_delimiter, ad_data);
				if("Y".equals(readResult[1])){
					value = readSimpleJson(readResult[0], true);
				}else{
					value = readSimpleJson(readResult[0], false);
				}
				result.appendKeyJsonValue(key, value);
				ad_delimiter.removeFirst();
				continue;
			}else if(delimiter == '}'){
				readResult = readJsonUnit(ad_delimiter, ad_data);
				if("Y".equals(readResult[1])){
					value = readSimpleJson(readResult[0], true);
				}else{
					value = readSimpleJson(readResult[0], false);
				}
				result.appendKeyJsonValue(key, value);
				ad_delimiter.removeFirst();
				return result;
			}else{
				throw new NotValidJsonDelimiterQueue(StringUtils.concat(" not valid delimiter[",String.valueOf(delimiter),"] after :"));
			}
			
			delimiter = ad_delimiter.peekFirst();
			if(delimiter == null){
				throw new NotValidJsonDelimiterQueue(StringUtils.concat(" after data delimiter is null. "));
			}else if(delimiter == ','){
				ad_delimiter.removeFirst();
				continue;
			}else if(delimiter == '}'){
				ad_delimiter.removeFirst();
				return result;
			}else{
				throw new NotValidJsonDelimiterQueue(StringUtils.concat(" except , and } others are not valid delimiter[",String.valueOf(delimiter),"]"));
			}
		}
	}
	
	
	public static Json asJson(ArrayDeque<Character> ad_delimiter, ArrayDeque<String> ad_data) throws NotValidJsonDataQueue, NotValidJsonDelimiterQueue{
		if(ad_delimiter == null || ad_data == null){
			return null;
		}
		if(ad_delimiter.isEmpty()){
			if(ad_data.isEmpty()){
				return null;
			}else{
				return readSimpleJson(ad_data.getFirst(), false);
			}
		}
		
		Character delimiter = ad_delimiter.removeFirst();
		if(delimiter == '{'){
			return readJsonObject(ad_delimiter, ad_data);
		}else if(delimiter == '['){
			return readJsonArray(ad_delimiter, ad_data);
		}else if(delimiter == '"' || delimiter == '\''){
			Character nextChar = ad_delimiter.peekFirst();
			if( nextChar == null || (nextChar != '\'' && nextChar != '"')){
				throw new NotValidJsonDelimiterQueue(StringUtils.concat(" not enclosed quotation marks."));
			}
			ad_delimiter.addFirst(delimiter);
			String[] stringResult = readJsonUnit(ad_delimiter, ad_data);
			if("Y".equals(stringResult[1])){
				return readSimpleJson(stringResult[0], true);
			}else{
				return readSimpleJson(stringResult[0], false);
			}
			
		}else{
			throw new NotValidJsonDelimiterQueue(StringUtils.concat(" delimiter of [",String.valueOf(delimiter),"] is not allowd to be the first delimiter"));
		}
		
	}
	
	public static Json asJson(String jsonString) throws NotValidJsonString, NotValidJsonDataQueue, NotValidJsonDelimiterQueue{
		ArrayDeque<Character> ad_delimiter = new ArrayDeque<Character>(); 
		ArrayDeque<String> ad_data = new ArrayDeque<String>();
		readJson(jsonString, ad_delimiter, ad_data);
		return asJson(ad_delimiter, ad_data);
	}
	
	/*
	public static Json asJson(String jsonString){
		if(jsonString == null){
			return null;
		}
		jsonString = jsonString.trim();
		if(jsonString.startsWith("{") && jsonString.endsWith("}")){
			//Process Json Object 
			Json json = JsonUtils.createJsonObject();
			
		}else if(jsonString.startsWith("[") && jsonString.endsWith("]")){
			//Process Json Array
			Json json = JsonUtils.createJsonArray();
			
			
		}else if(jsonString.startsWith("\"") && jsonString.endsWith("\"")){
			//Process Json String
			Json json = null;
			if(jsonString.length() == 2){
				json = JsonUtils.createSimpleValueJson("");
			}else{
				json = JsonUtils.createSimpleValueJson(jsonString.substring(1, jsonString.length() - 1));
			}
			return json;
		}else{
			//Process Json Number(Integer, Long, Double)
			Json json = null;
			if(jsonString.matches("(+|-)?[0-9]+")){
				try{
					Integer firstTry = Integer.parseInt(jsonString);
					json = JsonUtils.createSimpleValueJson(firstTry);
					return json;
				}catch(Exception e){
					logger.debug(e);
				}
				try{
					Long secondTry = Long.parseLong(jsonString);
					json = JsonUtils.createSimpleValueJson(secondTry);
					return json;
				}catch(Exception e){
					logger.debug(e);
				}
				logger.fatal(StringUtils.concat(jsonString, " can't be converted into Integer or Long"));
				return null;
			}else if(jsonString.matches("(+|-)?[0-9]*\\.[0-9]*")){
				try{
					Double firstTry = Double.parseDouble(jsonString);
					json = JsonUtils.createSimpleValueJson(firstTry);
					return json;
				}catch(Exception e){
					logger.debug(e);
				}
				logger.fatal(StringUtils.concat(jsonString, " can't be converted into Double"));
				return null;
			}else{
				return JsonUtils.createSimpleValueJson(jsonString);
			}
			
		}
		return null;
	}
	*/
	public static void main(String args[]) throws NotValidJsonString, NotValidJsonDataQueue, NotValidJsonDelimiterQueue{
		String jsonString = "{a:'asdfasdfsafsdf\n\rasdfasf'}";
		ArrayDeque<Character> ad_delimiter = new ArrayDeque<Character>(); 
		ArrayDeque<String> ad_data = new ArrayDeque<String>();
		readJson(jsonString, ad_delimiter, ad_data);
		System.out.println(ad_delimiter);
		System.out.println(ad_data);
		Json tempdata = asJson(jsonString);
		System.out.println(tempdata.asString());
	}
}
